package com.mouse.magent.web.config;

import com.mouse.magent.common.entity.common.Result;
import com.mouse.magent.common.exception.BaseException;
import com.mouse.magent.common.exception.SystemErrorType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;

import java.util.List;

@RestControllerAdvice
@Slf4j
public class ExceptionHandlerAdvice implements ErrorController {
    @Override
    public String getErrorPath() {
        return "/error";
    }

    @RequestMapping(value = {"/error"})
    @ResponseBody
    public Result error() {
        return Result.fail(SystemErrorType.URL_ERROR);
    }


    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    public Result serviceException(MethodArgumentNotValidException ex) {
        log.error("service exception:{}", ex.getMessage());
        return validResult(ex.getBindingResult());
    }

    @ExceptionHandler(BindException.class)
    public Result bindExceptionHandler(BindException ex) {
        log.error("service exception:{}", ex.getMessage());
        return validResult(ex.getBindingResult());
    }

    @ExceptionHandler(value = {MissingServletRequestParameterException.class})
    public Result missingServletRequestParameterException(MissingServletRequestParameterException ex) {
        log.error("missing servlet request parameter exception:{}", ex.getMessage());
        return Result.fail(SystemErrorType.ARGUMENT_NOT_VALID);
    }

    @ExceptionHandler(value = {MultipartException.class})
    public Result uploadFileLimitException(MultipartException ex) {
        log.error("upload file size limit:{}", ex.getMessage());
        return Result.fail(SystemErrorType.UPLOAD_FILE_SIZE_LIMIT);
    }

    @ExceptionHandler(value = {BaseException.class})
    public Result baseException(BaseException ex) {
        log.error("base exception:{}", ex.getErrorType().getMessage());
        return Result.fail(ex.getErrorType());
    }

    @ExceptionHandler(value = {Exception.class})
    public Result exception(Exception ex) {
        log.error(ex.getMessage(), ex);
        return Result.fail();
    }

    @ExceptionHandler(value = {HttpMessageNotReadableException.class})
    public Result httpMessageNotReadableException(HttpMessageNotReadableException ex) {
        log.error(ex.getMessage(), ex);
        return Result.fail();
    }

    @ExceptionHandler(value = {Throwable.class})
    public Result throwable() {
        return Result.fail();
    }

    /**
     * 校验参数自定义异常信息
     */
    private Result validResult(BindingResult bindingResult) {
        String message = "";
        try {
            List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            FieldError fieldError = fieldErrors.get(0);
            String field = fieldError.getField();
            String defaultMessage = fieldError.getDefaultMessage();
            message = field + defaultMessage;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        Result result = null;
        SystemErrorType systemErrorType = SystemErrorType.ARGUMENT_NOT_VALID;
        if ("".equals(message)) {//全局校验信息
            result = Result.fail(systemErrorType);
        } else {
            result = new Result(systemErrorType.getCode(), message);
        }
        return result;
    }

}
